var Canvas2Image = function() {
    var $support = function() {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d');

        return {
            canvas: !!ctx,
            imageData: !!ctx.getImageData,
            dataURL: !!canvas.toDataURL,
            btoa: !!window.btoa
        };
    }();

    var downloadMime = 'image/octet-stream';

    function scaleCanvas(canvas, width, height) {
        var w = canvas.width,
            h = canvas.height;
        if (width == undefined) {
            width = w;
        }
        if (height == undefined) {
            height = h;
        }

        var retCanvas = document.createElement('canvas');
        var retCtx = retCanvas.getContext('2d');
        retCanvas.width = width;
        retCanvas.height = height;
        retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);
        return retCanvas;
    }

    function getDataURL(canvas, type, width, height) {
        canvas = scaleCanvas(canvas, width, height);
        return canvas.toDataURL(type);
    }

    function saveFile(strData) {
        document.location.href = strData;
    }

    var saveFile1 = function(data, filename) {
        var save_link = document.createElement( 'a');
        save_link.href = data;
        save_link.download = filename;

        var event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        save_link.dispatchEvent(event);
    };

    function genImage(strData) {
        var img = document.createElement('img');
        img.src = strData;
        return img;
    }

    function fixType(type) {
        type = type.toLowerCase().replace(/jpg/i, 'jpeg');
        var r = type.match(/png|jpeg|bmp|gif/)[0];
        return 'image/' + r;
    }

    function encodeData(data) {
        if (!window.btoa) {
            throw 'btoa undefined'
        }
        var str = '';
        if (typeof data == 'string') {
            str = data;
        } else {
            for (var i = 0; i < data.length; i++) {
                str += String.fromCharCode(data[i]);
            }
        }

        return btoa(str);
    }

    function getImageData(canvas) {
        var w = canvas.width,
            h = canvas.height;
        return canvas.getContext('2d').getImageData(0, 0, w, h);
    }

    function makeURI(strData, type) {
        return 'data:' + type + ';base64,' + strData;
    }

    var genBitmapImage = function(oData) {

        var biWidth = oData.width;
        var biHeight = oData.height;
        var biSizeImage = biWidth * biHeight * 3;
        var bfSize = biSizeImage + 54; 

        var BITMAPFILEHEADER = [
            0x42, 0x4D,
            bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
            0, 0,
            0, 0,
            54, 0, 0, 0
        ];

        var BITMAPINFOHEADER = [
            40, 0, 0, 0,
            biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
            biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
            1, 0,
            24, 0,
            0, 0, 0, 0,
            biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0
        ];

        var iPadding = (4 - ((biWidth * 3) % 4)) % 4;

        var aImgData = oData.data;

        var strPixelData = '';
        var biWidth4 = biWidth << 2;
        var y = biHeight;
        var fromCharCode = String.fromCharCode;

        do {
            var iOffsetY = biWidth4 * (y - 1);
            var strPixelRow = '';
            for (var x = 0; x < biWidth; x++) {
                var iOffsetX = x << 2;
                strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) +
                    fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) +
                    fromCharCode(aImgData[iOffsetY + iOffsetX]);
            }

            for (var c = 0; c < iPadding; c++) {
                strPixelRow += String.fromCharCode(0);
            }

            strPixelData += strPixelRow;
        } while (--y);

        var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);

        return strEncoded;
    };

    var getImage = function(canvas, width, height, type) {
        if ($support.canvas && $support.dataURL) {
            if (typeof canvas == "string") {
                canvas = document.getElementById(canvas);
            }
            if (type == undefined) {
                type = 'png';
            }
            type = fixType(type);
            if (true || /bmp/.test(type)) {
                var data = getImageData(scaleCanvas(canvas, width, height));
                var strData = genBitmapImage(data);
                saveFile(makeURI(strData, downloadMime));
            } else {
                var strData = getDataURL(canvas, type, width, height);
                return strData;
            }
        }
    }

    var saveAsImage = function(canvas, width, height, type) {
        if ($support.canvas && $support.dataURL) {
            if (typeof canvas == "string") {
                canvas = document.getElementById(canvas);
            }
            if (type == undefined) {
                type = 'png';
            }
            type = fixType(type);
            if (/bmp/.test(type)) {
                var data = getImageData(scaleCanvas(canvas, width, height));
                var strData = genBitmapImage(data);
                saveFile(makeURI(strData, downloadMime));
            } else {
                var fileName = 'pic_' + (new Date()).getTime() + '.' + 'png';
                canvas.toBlob(function (blob) {
                    var eleLink = document.createElement('a');
                    eleLink.download = fileName;
                    eleLink.style.display = 'none';
                    // 字符内容转变成blob地址
                    eleLink.href = URL.createObjectURL(blob);
                    // 触发点击
                    document.body.appendChild(eleLink);
                    eleLink.click();
                    // 然后移除
                    document.body.removeChild(eleLink);
                },'image/png',1);

                // var strData = getDataURL(canvas, type, width, height);
                // var filename = 'pic_' + (new Date()).getTime() + '.' + 'png';
                // saveFile1(strData, filename);

            }
        }
    };

    var convertToImage = function(canvas, width, height, type) {
        if ($support.canvas && $support.dataURL) {
            if (typeof canvas == "string") {
                canvas = document.getElementById(canvas);
            }
            if (type == undefined) {
                type = 'png';
            }
            type = fixType(type);

            if (/bmp/.test(type)) {
                var data = getImageData(scaleCanvas(canvas, width, height));
                var strData = genBitmapImage(data);
                return genImage(makeURI(strData, 'image/bmp'));
            } else {
                var strData = getDataURL(canvas, type, width, height);
                return genImage(strData);
            }
        }
    };

    return {

        getImage: getImage,
        getPNG: function(canvas, width, height) {
            return getImage(canvas, width, height, 'png');
        },
        getJPEG: function(canvas, width, height) {
            return getImage(canvas, width, height, 'jpeg');
        },
        getGIF: function(canvas, width, height) {
            return getImage(canvas, width, height, 'gif');
        },
        getBMP: function(canvas, width, height) {
            return getImage(canvas, width, height, 'bmp');
        },


        saveAsImage: saveAsImage,
        saveAsPNG: function(canvas, width, height) {
            return saveAsImage(canvas, width, height, 'png');
        },
        saveAsJPEG: function(canvas, width, height) {
            return saveAsImage(canvas, width, height, 'jpeg');
        },
        saveAsGIF: function(canvas, width, height) {
            return saveAsImage(canvas, width, height, 'gif');
        },
        saveAsBMP: function(canvas, width, height) {
            return saveAsImage(canvas, width, height, 'bmp');
        },

        convertToImage: convertToImage,
        convertToPNG: function(canvas, width, height) {
            return convertToImage(canvas, width, height, 'png');
        },
        convertToJPEG: function(canvas, width, height) {
            return convertToImage(canvas, width, height, 'jpeg');
        },
        convertToGIF: function(canvas, width, height) {
            return convertToImage(canvas, width, height, 'gif');
        },
        convertToBMP: function(canvas, width, height) {
            return convertToImage(canvas, width, height, 'bmp');
        }
    };

}();